home *** CD-ROM | disk | FTP | other *** search
/ Space & Astronomy / Space and Astronomy (October 1993).iso / mac / VIEWERS / X11 / XLOADIMG.TAR / rle.c < prev    next >
C/C++ Source or Header  |  1991-05-20  |  11KB  |  440 lines

  1. /* 
  2.  * rle - read in a Utah RLE Toolkit type image.
  3.  * 
  4.  * Author:    Graeme Gill
  5.  * Date:     30/5/90
  6.  * 
  7.  * Bugs - doesn't free up memory used by rle functions.
  8.  *
  9.  */
  10.  
  11. #undef  DEBUG
  12.  
  13. #ifdef DEBUG
  14. # define debug(xx)    fprintf(stderr,xx)
  15. #else
  16. # define debug(xx)
  17. #endif
  18.  
  19.  
  20. #define MIN(a,b) ( (a)<(b) ? (a) : (b))
  21.  
  22. #include <math.h>
  23. #include <stdio.h>
  24. #include "image.h"
  25. #include "rle.h"
  26.  
  27. void dithermap();
  28.  
  29. /* input file stuff */
  30. static int ptype;                /* picture type : */
  31. #define BW_NM    0        /* black and white, no map */
  32. #define BW_M    1        /* black and white, and a map */
  33. #define SC_M    2        /* single colour channel and colour map */
  34. #define C_NM    3        /* full colour, no maps */
  35. #define C_M        4        /* full colour with colour maps */
  36. static rle_pixel **fmaps;        /* file colour maps from buildmap() */
  37. static unsigned char **scan;    /* buffer for input data */
  38. static int x_min;        /* copy of picture x_min */
  39. static int y_min;        /* copy of picture y_min */
  40.  
  41. /* option stuff (Not functional) */
  42. static float disp_gam = 1.0;    /* default display gamma correction factor */
  43. static int iflag=0;            /* user suplied image gamma */
  44. static float img_gam = 1.0;            /* image gamma */
  45. static int bwflag = 0;            /* black and white flag */
  46. static int gammamap[256];
  47. static int background[3] = {0,0,0};    /* our background colour */
  48.  
  49. /* stuff for dithering colour pictures */
  50. int colmap[216][3];        /* for dither map */
  51. int magic[16][16];
  52. int modN[256];
  53. int divN[256];
  54.  
  55. int rleIdent(fullname, name)
  56.      char *fullname, *name;
  57. {
  58.   ZFILE *rlefile;
  59.   int x_len,y_len;
  60.   int rv;
  61.  
  62.   debug("rleIdent called\n");
  63.   rlefile = zopen(fullname);
  64.   if(!rlefile)
  65.     {
  66.       perror("rleIdent: Unable to open file");
  67.       return(0);
  68.     }
  69.   debug("rleIdent: Opened file ok\n");
  70.   sv_globals.svfb_fd = rlefile;
  71.   rv = rle_get_setup(&sv_globals);
  72.   debug("rleIdent: got setup ok\n");
  73.   zclose(rlefile);
  74.   debug("rleIdent: closed file ok\n");
  75.   switch(rv)
  76.     {
  77.     case -1:
  78.       return 0;        /* Not rle format */
  79.     case 0:
  80.       /* now figure out the picture type */
  81.       switch(sv_globals.sv_ncolors)
  82.     {
  83.     case 0:
  84.       perror("rleIdent: no colour channels to display");
  85.       return(0);
  86.     case 1:
  87.       x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
  88.       y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
  89.       printf("%s is a %dx%d", name, x_len, y_len);
  90.       switch(sv_globals.sv_ncmap) {
  91.         case 0:
  92.           /* black and white, no map */
  93.           printf(" 8 bit grey scale RLE image with no map\n"); 
  94.           break;
  95.         case 1:
  96.           /* black and white with a map */
  97.           printf(" 8 bit grey scale RLE image with map\n"); 
  98.           break;
  99.         case 3:
  100.           /* single channel encoded colour with decoding map */
  101.           printf(" 8 bit color RLE image with color map\n");
  102.           break;
  103.         default:
  104.           perror(" 8 bit RLE image with an illegal color map\n");
  105.           return 0;
  106.         }
  107.       break;
  108.     case 3:
  109.       x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
  110.       y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
  111.       printf("%s is a %dx%d", name, x_len, y_len);
  112.       switch(sv_globals.sv_ncmap)
  113.         {
  114.         case 0:
  115.           printf(" 24 bit color RLE image with no map\n");
  116.           break;
  117.         case 3:
  118.           printf(" 24 bit color RLE image with colour map\n");
  119.           break;
  120.         default:
  121.           printf(" 24 bit color RLE image with an illegal color map\n");
  122.           return 0;
  123.         }
  124.       break;
  125.     default:
  126.       x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
  127.       y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
  128.       printf("%s is a %dx%d", name, x_len, y_len);
  129.       printf(" RLE image with an illegal number of color planes\n");
  130.       return 0;
  131.     }
  132.       return 1;
  133.     default:            /* Some sort of error */
  134.       /*            perror("rleIdent");*/
  135.       return 0;
  136.     }
  137. }
  138.  
  139. Image *rleLoad(fullname,name,verbose)
  140.      char *fullname,*name;
  141.      unsigned int verbose;
  142. {
  143.   int x_len, y_len;
  144.   int i,j;
  145.   ZFILE *rlefile;
  146.   int ncol;            /* number of colors */
  147.   int depth;
  148.   unsigned char *bufp;
  149.   Image *image;
  150.   unsigned char *buf;
  151.   
  152.   dith_levels = 256;    /* aim for 128 levels of each colour */
  153.   
  154.   debug("rleLoad called\n");
  155.   rlefile = zopen(fullname);
  156.   if(!rlefile)
  157.     {
  158.       perror("rleLoad: Cannot open input file");
  159.       return(NULL);    
  160.     }
  161.   sv_globals.svfb_fd = rlefile;
  162.   debug("rleLoad: About to call get_setup\n");
  163.   if(rle_get_setup( &sv_globals )) {
  164.     zclose(rlefile);
  165.     return(NULL);    
  166.   }
  167.   
  168.   debug("rleLoad: get_setup called ok\n");
  169.   if(iflag == 1)    /* -i flag */
  170.     img_gam = 1.0/img_gam;        /* convert to display gamma */
  171.   
  172.   /* If no image gamma on command line, check comments in file */
  173.   if (!iflag)
  174.     {
  175.       char * v;
  176.       if ( (v = rle_getcom( "image_gamma", &sv_globals )) != NULL )
  177.     {    
  178.       img_gam = atof( v );
  179.       /* Protect against bogus information */
  180.       if ( img_gam == 0.0 )
  181.         img_gam = 1.0;
  182.       else
  183.         img_gam = 1.0 / img_gam;    /* convert to display gamma */
  184.     }
  185.       else if ( (v = rle_getcom( "display_gamma", &sv_globals )) != NULL )
  186.     {
  187.       img_gam = atof( v );
  188.       /* Protect */
  189.       if ( img_gam == 0.0 )
  190.         img_gam = 1.0;
  191.     }
  192.     }
  193.   
  194.   x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
  195.   y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
  196.   
  197.   x_min = sv_globals.sv_xmin;
  198.   y_min = sv_globals.sv_ymin;
  199.   
  200.   /* fix this so that we don't waste space */
  201.   sv_globals.sv_xmax -= sv_globals.sv_xmin;
  202.   sv_globals.sv_xmin = 0;
  203.   
  204.   /* turn off the alpha channel (don't waste time and space)*/
  205.   sv_globals.sv_alpha = 0;
  206.   SV_CLR_BIT(sv_globals,SV_ALPHA);
  207.   
  208.   /* for now, force background clear */
  209.   if(sv_globals.sv_background ==1)    /* danger setting */
  210.     {
  211.       debug("Forcing clear of background\n");
  212.       sv_globals.sv_background = 2;
  213.       if(sv_globals.sv_bg_color==0)    /* if none allocated */
  214.     sv_globals.sv_bg_color = background;    /* use this one */
  215.     }
  216.   
  217.   /* now figure out the picture type */
  218.   switch(sv_globals.sv_ncolors)
  219.     {
  220.     case 0:
  221.       perror("rleLoad: no colour channels to display");
  222.       zclose(rlefile);
  223.       return(NULL);
  224.     case 1:
  225.       switch(sv_globals.sv_ncmap)
  226.     {
  227.     case 0:
  228.       ptype = BW_NM;    /* black and white, no map */
  229.       break;
  230.     case 1:
  231.       ptype = BW_M;    /* black and white with a map */
  232.       break;
  233.     case 3:
  234.       ptype = SC_M;    /* single channel encoded colour with decoding map */
  235.       break;
  236.     default:
  237.       zclose(rlefile);
  238.       perror("rleLoad: Illegal number of maps for one colour channel");
  239.       return(NULL);
  240.     }
  241.       break;
  242.     case 3:
  243.       switch(sv_globals.sv_ncmap)
  244.     {
  245.     case 0:
  246.       ptype = C_NM;    /* colour, no map */
  247.       break;
  248.     case 3:
  249.       ptype = C_M;    /* colour with maps */
  250.       break;
  251.     default:
  252.       perror("rleLoad: Illegal number of maps for colour picture");
  253.       zclose(rlefile);
  254.       return(NULL);
  255.     }
  256.       break;
  257.     default:
  258.       perror("rleLoad: Illegal number of colour channels");
  259.       zclose(rlefile);
  260.       return(NULL);
  261.     }
  262.   
  263.   if(verbose)
  264.     {
  265.       printf("%s is a %dx%d",name,x_len,y_len);
  266.       switch(ptype)
  267.     {
  268.     case BW_NM:
  269.       printf(" 8 bit grey scale RLE image with no map"); 
  270.       break;
  271.     case BW_M:
  272.       printf(" 8 bit grey scale RLE image with map"); 
  273.       break;
  274.     case SC_M:
  275.       printf(" 8 bit RLE image with colour map");
  276.       break;
  277.     case C_NM:
  278.       printf(" 24 bit RLE image with no map (will dither to 8 bits)");
  279.       break;
  280.     case C_M:
  281.       printf(" 24 bit RLE image with color map (will dither to 8 bits)");
  282.       break;
  283.     }
  284.       printf(", with gamma of %4.2f\n",img_gam);
  285.     }
  286.   znocache(rlefile);
  287.   
  288.   if(ptype==SC_M)
  289.     {    /* don't mess with the image, but change their colour map a bit if needed */
  290.       disp_gam /= img_gam;    /* amount to change their map */
  291.       img_gam = 1.0;        /*  not to the image coming in */
  292.     }
  293.   
  294.   /* get hold of the colour maps, and set to undo their images gamma */
  295.   fmaps = buildmap(&sv_globals,sv_globals.sv_ncolors,img_gam);
  296.   
  297.   /* now we had better sort out the picture data */
  298.   debug("done colour map\n");
  299.   
  300.   /* rle stufff */
  301.   /* Get space for a full colour scan line */
  302.   scan = (unsigned char **) lmalloc( (sv_globals.sv_ncolors +
  303.                       sv_globals.sv_alpha) *
  304.                     sizeof( unsigned char * ) );
  305.   for ( i = 0; i < sv_globals.sv_ncolors + sv_globals.sv_alpha; i++ )
  306.     scan[i] = (unsigned char *)lmalloc(x_len);
  307.   if ( sv_globals.sv_alpha )
  308.     scan++;
  309.   debug("got space for get_row\n");
  310.   
  311.   depth = 8;        /* We always supply 8bit images */
  312.   image = newRGBImage(x_len,y_len,depth);
  313.   image->title = dupString(name);
  314.   debug("got image structure\n");
  315.   
  316.   buf = image->data;
  317.   
  318.   /* If we are going to dither - then create the dither matrix. */
  319.   if(!bwflag && ptype!=SC_M && ptype != BW_NM && ptype != BW_M)
  320.     {
  321.       dith_np2 = 1;        /* allow non-power of 2 dither map size */
  322.       dithermap( 6, disp_gam, colmap, divN, modN, magic );
  323.     }
  324.   
  325.   debug("About to read image in\n");
  326.   bufp = buf + (y_len-1) * x_len;
  327.   for(j=y_len;j>0;j--,bufp -= x_len)
  328.     {
  329.       rle_getrow(&sv_globals,scan);
  330.       switch(ptype)
  331.     {
  332.     case SC_M:
  333.       memcpy(bufp,&scan[0][0],x_len);
  334.       break;
  335.     case BW_NM:
  336.     case BW_M:
  337.       bw_m_line(bufp,x_len);
  338.       break;
  339.     case C_NM:
  340.     case C_M:
  341.       c_m_line(bufp,x_len,j);
  342.       break;
  343.     }
  344.     }
  345.   debug("Image Read in\n");
  346.   
  347.   /* Deal with colour maps */
  348.   /* set up our gamma correction */
  349.   make_gamma(disp_gam,gammamap);    /* we'll need it */
  350.   
  351.   debug("Creating color map\n");
  352.   /* now load an appropriate colour map */
  353.   if(!bwflag && ptype==SC_M)
  354.     {
  355.       /* use their maps  & correct their gamma */
  356.       ncol = 1<<sv_globals.sv_cmaplen;    /* number of entries */
  357.       for(i=0;i<ncol;i++)
  358.     {
  359.       *(image->rgb.red + i) = gammamap[fmaps[0][i]]<<8;
  360.       *(image->rgb.green + i) = gammamap[fmaps[1][i]]<<8;
  361.       *(image->rgb.blue + i) = gammamap[fmaps[2][i]]<<8;
  362.     }
  363.     }
  364.   else if(bwflag || ptype == BW_NM || ptype == BW_M)
  365.     {
  366.       /* load a black and white map (gamma corrected for this display)*/
  367.       ncol = 256;            /* don't know whats been used */
  368.       for(i=0;i<ncol;i++)
  369.     {
  370.       *(image->rgb.red + i) = 
  371.         *(image->rgb.green + i) = 
  372.           *(image->rgb.blue + i) = gammamap[i]<<8;
  373.     }
  374.     }
  375.   else
  376.     {
  377.       /* must be colour, so use dither map (gamma corrected for this display)*/
  378.       ncol = 6*6*6;
  379.       /* Dither map has already been created above */
  380.       for(i = 0; i < ncol; i++)
  381.     {
  382.       *(image->rgb.red + i) = colmap[i][0]<<8;
  383.       *(image->rgb.green + i) = colmap[i][1]<<8;
  384.       *(image->rgb.blue + i) = colmap[i][2]<<8;
  385.     }
  386.     }
  387.   image->rgb.used = ncol;
  388.   
  389.   zclose(rlefile);
  390.   debug("finished\n");
  391.   return(image);
  392. }
  393.  
  394. #define DMAP(v,x,y)    (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v])
  395.  
  396. /* run the black and white through its map */
  397. bw_m_line(dp,number)
  398.      int number;
  399.      register unsigned char *dp;
  400. {
  401.   register unsigned char *r;
  402.   register int i;
  403.   
  404.   for(i=number,r= &scan[0][0];i>0;i--,r++,dp++)
  405.     {
  406.       *dp = fmaps[0][*r];
  407.     }
  408. }
  409.  
  410. /* convert a colour line with map to 8 bits per pixel */
  411. c_m_line(dp,number,line)
  412.      int number,line;
  413.      register unsigned char *dp;
  414. {
  415.   register unsigned char *r, *g, *b;
  416.   register int i, col, row;
  417.   
  418.   if(!bwflag)
  419.     {        
  420.       for ( row = line % dith_size, col = x_min % dith_size, i = number, r = &scan[0][0]
  421.        ,g= &scan[1][0], b= &scan[2][0];
  422.        i > 0; i--, r++, g++, b++, dp++, col = ((col + 1) % dith_size) )
  423.     {
  424.       *dp = DMAP(fmaps[0][*r], col, row) +
  425.         DMAP(fmaps[1][*g], col, row) * 6 +
  426.           DMAP(fmaps[2][*b], col, row) * 36;
  427.     }
  428.     }
  429.   else
  430.     {
  431.       int red,green,blue;
  432.       for (i = number, r= &scan[0][0], g= &scan[1][0]
  433.        ,b= &scan[2][0]; i>0;i--,r++,g++,b++,dp++)
  434.     {
  435.       red = fmaps[0][*r];green=fmaps[1][*g];blue = fmaps[2][*b];
  436.       *dp = 0.35* red + 0.55* green + 0.1* blue;
  437.     }
  438.     }
  439. }
  440.